package org.examples.java.util;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.ServiceLoader;

import org.junit.Test;

public class ServiceLoaderTest {

    @Test
    public void testReload() throws IOException {
        URL configFileUrl = ClassLoader.getSystemResource("META-INF/services/org.examples.java.util.MyService");
        FileReader in = new FileReader(configFileUrl.getPath());
        StringBuilder backup = new StringBuilder();
        for(int c; (c = in.read()) != -1;)
            backup.append((char)c);
        in.close();

        try
        {
            ServiceLoader<MyService> serviceLoader = ServiceLoader.load(MyService.class);

            Iterator<MyService> iterator = serviceLoader.iterator();
            MyService helloService = iterator.next();
            assertTrue(helloService instanceof HelloService);
            assertEquals("Hello", helloService.getText());
            MyService byeService = iterator.next();
            assertTrue(byeService instanceof ByeService);
            assertFalse(iterator.hasNext());

            FileWriter configFileOut = new FileWriter(configFileUrl.getPath());
            configFileOut.write("org.examples.java.util.HowAreYouService");
            configFileOut.close();

            serviceLoader.reload();

            Iterator<MyService> iterator2 = serviceLoader.iterator();
            MyService howAreYouService = iterator2.next();
            assertTrue(howAreYouService instanceof HowAreYouService);
            assertFalse(iterator2.hasNext());

        }
        finally {
            FileWriter configFileOut = new FileWriter(configFileUrl.getPath());
            configFileOut.write(backup.toString());
            configFileOut.close();
        }

    }

    @Test
    public void testLoadClassOfSClassLoader() {
        // Extension class loader does not see the user classes
        ServiceLoader<MyService> serviceLoader = ServiceLoader.load(MyService.class, this.getClass().getClassLoader()
            .getParent());

        Iterator<MyService> iterator = serviceLoader.iterator();
        assertFalse(iterator.hasNext());
    }

    @Test
    public void testLoadClassOfS() {
        ServiceLoader<MyService> serviceLoader = ServiceLoader.load(MyService.class);

        Iterator<MyService> iterator = serviceLoader.iterator();
        MyService helloService = iterator.next();
        assertTrue(helloService instanceof HelloService);
        assertEquals("Hello", helloService.getText());

        MyService byeService = iterator.next();
        assertTrue(byeService instanceof ByeService);
        assertEquals("Bye", byeService.getText());

        assertFalse(iterator.hasNext());
        assertEquals("java.util.ServiceLoader[" + MyService.class.getName() + "]", serviceLoader.toString());
    }

    @Test
    public void testLoadInstalled() {
        // Extension class loader does not see the user classes
        ServiceLoader<MyService> serviceLoader = ServiceLoader.loadInstalled(MyService.class);

        Iterator<MyService> iterator = serviceLoader.iterator();
        assertFalse(iterator.hasNext());
    }

}
